home *** CD-ROM | disk | FTP | other *** search
- #include "lack.h"
- #include "sysvars.h"
- #include "xbra.h"
- #include <string.h>
- #include <osbind.h>
- #include <mintbind.h>
-
- lap *lapps[NUM_APPS];
- lap *curapp;
-
- struct save_area
- {
- int in_use;
- long dregs[8]; /* These are gem's registers at the time of the
- * task switch. User's registers are pushed onto
- * the usp. */
- void (*stopped)(); /* Where the task switch was called from. */
- long aregs[6]; /* a1-a6 as dregs */
- void *g_ssp; /* + 0x3e */
- void *usp; /* + 0x42 */
- void *u_ssp; /* + 0x46 */
- };
-
- ki;
-
- int in_aes; /* are we servicing an aes call, rather than letting some apid run */
- int get_menu_title; /* let the controler acc's do menu_register? */
- int aes_active; /* I don't know how to keep this thing up to date */
- int aes_version;
- struct save_area *apid0_save=NULL; /* test for wether apid 0 is the desktop, see below */
- struct appl *apid0_appl; /* " " " ... */
- int is_desk=FALSE;
- static int first=TRUE;
- int apid; /* the running application, to the best of my knowledge */
- int __desk_stk[1024];
- const long desk_stk=(long)&__desk_stk[1023];
- static void (*yield_aes)(void);
- void *os_base;
- /*void *os_end; I don't know how to set this */
-
- struct global_action *gl_action;
-
- /* in lack.s: */
- extern void trap_2(void);
- extern void trap_3(void);
- extern void trap_13(void);
- extern void _first_leave_aes(void);
- extern void _desk_leave_aes(void);
-
- /* in jump.s: */
- extern int setjump(lap *);
- extern int longjump(lap *);
-
- /* in wind.c: */
- extern void desk_zap_windows(void);
-
- /* vectors to search down before unloading acc, the first nine spaces are for
- * kbdvecs.
- * Maybe I should add mfp ints, or save everything which doesn't have the high
- * byte set. It does not take much memory to save these things and refer back
- * to them.
- * If you add vectors leave off the cast, and the error message will tell you
- * what NUM_VECS should be changed to.
- */
- #define NUM_VECS 54
- char **vecs[NUM_VECS]={(char **)0x0, (char **)0x0, (char **)0x0, (char **)0x0,
- (char **)0x0, (char **)0x0, (char **)0x0, (char **)0x0, (char **)0x0,
- (char **)0x08, (char **)0x0c, (char **)0x10, (char **)0x14, (char **)0x18,
- (char **)0x1c, (char **)0x20, (char **)0x24, (char **)0x2c, (char **)0x34,
- (char **)0x38, (char **)0x3c, (char **)0x60, (char **)0x70, (char **)0x84,
- (char **)0x88, (char **)0xb4, (char **)0xb8, (char **)0xc0, (char **)0xe0,
- (char **)0xe4, (char **)0xe8, (char **)0x114, (char **)0x400, (char **)0x404,
- (char **)0x408, (char **)0x42a, (char **)0x472, (char **)0x476, (char **)0x47e,
- (char **)0x4f6, (char **)0x506, (char **)0x50a, (char **)0x50e, (char **)0x512,
- (char **)0x51e, (char **)0x53e, (char **)0x55e, (char **)0x57e, (char **)0x108,
- (char **)0x118, (char **)0x124, (char **)0x128, (char **)0x12c, (char **)0x130};
-
- struct xbra gem= {XBRA_MAGIC, 0x6c61636bL /*'lack'*/, NULL, JMP_OPCODE,
- (void *)trap_2};
- struct xbra mytrap={XBRA_MAGIC, 0x6c61636bL /*'lack'*/, NULL, JMP_OPCODE,
- (void *)trap_3};
- struct xbra bios= {XBRA_MAGIC, 0x6c61636bL /*'lack'*/, NULL, JMP_OPCODE,
- (void *)trap_13};
- install_trap2()
- {
- long ssp;
- int sr;
- char *sp;
- char **kvecs;
- int c;
-
- kvecs=(char **)Kbdvbase(); /* this assumes Kbdbase returns the a pointer
- * to the actual vectors */
- for(c=0; c<9; c++)
- vecs[c]=kvecs++;
- ssp=Super(0);
- sr=spl7();
- os_base=(*_sysbase)->os_beg;
- gem.xb_old=*(void **)0x88L;
- *(short **)0x88L=&gem.xb_op;
- mytrap.xb_old=*(void **)0x8cL;
- *(short **)0x8cL=&mytrap.xb_op;
- bios.xb_old=*(void **)0xb4L;
- *(short **)0xb4L=&bios.xb_op;
- /* find apid0_appl */
- apid0_appl=aes_appl;
- while(apid0_appl->apid!=0 && apid0_appl->next)
- apid0_appl=apid0_appl->next;
- if(apid0_appl->apid!=0)
- {
- ALERT("could not find apid 0");
- apid0_appl=NULL;
- }else{
- DEBUG("apid 0 application structure at %lx", apid0_appl);
- apid0_save=(struct save_area *)apid0_appl->save_area;
- yield_aes=*(((void(**)())apid0_save->g_ssp) - 1);
- }
- lapps[0]->istk=desk_stk;
- if(!strncmp (apid0_appl->name, " ", 8))
- {
- /* at startup, anything will look like the desktop */
- DEBUG("lack: apid 0 is desktop");
- is_desk=TRUE;
- sp=(char *)apid0_save->g_ssp;
- if(*sp==0 || *longframe)
- /* if it isn't a 030, it can't have an address with the top
- * byte set, so this test for linef works */
- {
- lapps[0]->pc=*(void(**))sp;
- *(void(**))sp=_desk_leave_aes;
- aes_version=0x160; /* will be reset by lackcontrol's appl_init */
- DEBUG("tos >= 1.6");
- }else{
- lapps[0]->pc=*(void(**))(sp + 2);
- *(void(**))(sp + 2)=_desk_leave_aes;
- aes_version=0x140; /* will be reset by lackcontrol's appl_init */
- DEBUG("tos < 1.6");
- }
- }else{
- DEBUG("lack: apid 0 is not desktop");
- first=TRUE;
- sp=(char *)apid0_save->u_ssp;
- if(*longframe)
- {
- lapps[0]->pc=*(void(**))(sp + 4);
- *(void (**))(sp + 4)=_first_leave_aes;
- }else{
- lapps[0]->pc=*(void(**))(sp + 2);
- *(void(**))(sp + 2)=_first_leave_aes;
- }
- lapps[0]->in_aes=1;
- }DEBUG("changing pc %lx on stack %lx", lapps[0]->pc, sp);
- spl(sr);
- Super(ssp);
- }
-
- void
- get_gem_stack()
- {
- /* acc user and gem ssp's are on the same stack. The acc needs to
- * return from Dcntl(LA_INIT_ACC) while it's gem stack is in use.
- * So, we change the gem stack so the acc's ssp can be used for
- * Dcntl(LA_WAKE_APP) when it is time to return to the caller pid.
- * For the first acc, it needs to call Dcntl(LA_WAKE_APP) when gem
- * pid 0 is running, but MiNT lackontrol proccess is active, that
- * is, when apid 0 returns from the trap 2 call made by lackontrol.
- * I hope this makes some sense.
- */
- struct save_area *my_save;
- char *my_gem_stack;
- long ssp; int sr;
-
- my_gem_stack=(char *)Mxalloc(4096, M_PROT_S | M_ALT);
- curapp->mystk_base = curapp->mystk = (long)my_gem_stack+4096;
- my_gem_stack+=2048;
- ssp=Super(0);
- sr=spl7();
- my_save=aes_appl->save_area;
- DEBUG("changing gem's ssp from %lx to %lx", my_save->g_ssp, my_gem_stack);
- my_save->g_ssp=my_gem_stack;
- spl(sr);
- Super(ssp);
- }
-
- int
- check_for_desk(int was_desk)
- {
- char *sp;
-
- if(!strncmp(apid0_appl->name, " ", 8))
- {
- /* Make sure apid 0 is still the desktop */
- sp=(char *)apid0_save->g_ssp;
- if(aes_version > 0x140) /* notice that this differs from the rom rev */
- {
- /* save the pc of desktop and make it return to me, so I can
- * adjust the MiNT pid, etc. I figure the desktop call the
- * aes function dipatcher via line-f or jsr, (depending on wether
- * there is such a thing as line-f).
- */
- if (*(void(**))sp!=_desk_leave_aes)
- {
- lapps[0]->pc=*(void(**))sp;
- *(void(**))sp=_desk_leave_aes;
- DEBUG("changed pc %lx on stack %lx", lapps[0]->pc, sp);
- }
- }else{
- if(*(void(**))((char *)sp+2)!=_desk_leave_aes)
- {
- lapps[0]->pc=*(void(**))((char *)sp+2);
- *(void(**))((char *)sp+2)=_desk_leave_aes;
- DEBUG("changed pc %lx on stack %lx", lapps[0]->pc, sp);
- }
- }
- lapps[0]->in_aes=1;
- if (!was_desk) lapps[0]->istk=desk_stk;
- }else{
- is_desk=FALSE;
- if(was_desk) /* desktop has done wind_new */ desk_zap_windows();
- else /* an application has exited, but the desktop didn't
- * wake up. */
- DEBUG("not desktop");
- }
- }
-
- void
- print_global(AESP *call)
- {
- char line[80];
- int last=0;
- int count, *global=call->global;
-
- DEBUG("global array from call %d", call->control[0]);
- for(count=0; count<15; count++)
- {
- ksprintf(&line[last], "%x, ", global[count]);
- last=strlen(line);
- if(last>73)
- {
- DEBUG(line);
- last=0;
- }
- }
- if(last) DEBUG(line);
- }
-
- int
- unload()
- {
- /* this is called by handle_action during entry to or exit from aes */
- /* we certainly are putting alot of stuff on someone else's stack */
- AESP *old=_aesparams;
- int (*oldcall)()=__aes__;
- NEW_AESP(a);
- BASEPAGE *b=curapp->acc->base;
- char *start=b->p_tbase;
- char *end=start + b->p_tlen + b->p_dlen + b->p_blen;
- char *cur;
- char **prev=vecs[0];
- struct xbra *x;
- int c, sr, fail=0;
- char error_mess[90];
-
- DEBUG("unloading %s from apid %d", curapp->acc->name, apid);
- _aesparams=&a;
- a.global=old->global;
- __aes__=_super_aes;
- sr=spl7();
- /*all breaks but the last one: "if(fail)" break out of the while loop*/
- for(c=0; c<NUM_VECS; prev=vecs[++c])
- {
- while(1)
- {
- cur=*prev;
- if(!cur) break; /* this is for _shell_p */
- if(IS_XBRA(cur))
- {
- x=XBRA(cur);
- if(cur>start && cur < end)
- {
- *prev=x->xb_old;
- DEBUG("lack: unchaining from vector %lx", vecs[c]);
- break;
- }
- else if (XB_IS_JUMP(x))
- {
- if((char *)x->xb_func > start &&
- (char *)x->xb_func < end)
- {
- *prev=x->xb_old;
- DEBUG("lack: unchaining from vector %lx",
- vecs[c]);
- break;
- }
- }
- prev=(char **)&x->xb_old;
- }else{
- if(cur>start && cur<end)
- {
- fail=TRUE;
- ksprintf(error_mess,"[1][lack: could not unhook %s|from vector 0x%lx][ worthless program ]",
- curapp->acc->name, vecs[c]);
- }
- break;
- }
- }
- if (fail) break;
- }
- spl(sr);
- if(fail)
- {
- form_alert(3, error_mess);
- _aesparams=old;
- __aes__=oldcall;
- return -1;
- }
- Wind_new(&a);
- rsrc_free();
- _aesparams=old;
- __aes__=oldcall;
- curapp->in_aes=0;
- in_aes=FALSE;
- curapp->mystk=curapp->mystk_base;
- Pterm(0);
- }
-
- void
- handle_action()
- {
- int *todo=&curapp->action;
-
- switch(*todo)
- {
- case APPL_ALIVE:
- aes_active=TRUE;
- break;
- case APPL_KILL:
- *todo=0; /* unload will make aes calls, and do Pterm */
- unload();/* if it succeeds. */
- break;
- case APPL_INIT:
- if (aes_version<0x140)
- curapp->call->global[0]=0x140;
- curapp->call->global[1]=NUM_APPS;
- break;
- case WIND_CREATE:
- Wind_create(curapp->call);
- break;
- case RSRC_LOAD:
- print_global(curapp->call);
- default:
- }
- *todo=0;
- }
-
- void
- handle_gl_action()
- {
- struct global_action *this=gl_action;
- AESP *old=_aesparams;
- int (*oldcall)()=__aes__;
- NEW_AESP(a);
- int mess[8]={LA_KILL_ACC, apid, 0};
- int sr;
-
- _aesparams=&a;
- __aes__=_super_aes;
- a.global=curapp->call->global;
- while(this)
- {
- gl_action=this->next;
- if(lapps[this->apid]->action==APPL_KILL)
- {
- DEBUG("sending kill message to apid %d", this->apid);
- appl_write(this->apid, 16, mess);
- }
- sr=spl7();
- kfree(this);
- spl(sr);
- this=gl_action;
- }
- _aesparams=old;
- __aes__=oldcall;
- }
-
- void *
- leave_aes()
- {
- lap *a=lapps[cur_apid];
-
- if(apid != cur_apid)
- {
- if(!setjump(a))
- /* save this jump context for the current apid */
- {
- Dcntl(LA_WAKE_APP, "S:", a);
- /* wake up its corresponding processes */
- longjump(lapps[cur_apid]);
- /* always longjump upon waking */
- }
- apid=cur_apid;
- curapp=lapps[apid];
- }
- if(gl_action) handle_gl_action();
- if(curapp->action) handle_action();
- in_aes=FALSE; /* now what about my aes emulation call? */
- curapp->in_aes-=1;
- if(apid==0)
- {
- if(is_desk || first)
- /* _desk_leave_aes intercepts the desktop as gem wakes it up,
- * leave_aes() will set mystk to the desktop's stack, when a
- * program is launched, we want mystk to be set to desk_stk.
- */
- {
- if (first) first=FALSE;
- curapp->mystk=desk_stk;
- return(curapp->pc);
- }
-
- }
- return NULL;
- }
-
- /* Returns 0 if this call should be passed to the aes, otherwise returns 1.
- * When aes calls are made from within enter_aes or leave_aes, they are sent
- * directly to gem. */
- int
- enter_aes(AESP *call, void(**pc)())
- {
- int cmd, done=0;
-
- if(gl_action) handle_gl_action();
- if(apid != cur_apid)
- {
- ALERT("lack: I thought this was apid %d, but gem says it is %d",
- apid, cur_apid);
- apid=cur_apid;
- }
- curapp->call=call;
- curapp->in_aes+=1;
- if(curapp->action)
- handle_action();
- cmd=call->control[0];
- /* The action APPL_KILL sets control[0] to APPL_KILL in order to force
- * immediate return from the aes call.
- */
- TRACE("apid %d calling aes command %d", apid, cmd);
- if (curapp->in_aes==1) curapp->pc=(void(*)())pc;
- /* If we think it is the desktop, we check that the aes agrees, then we
- * make sure it is set up to return from aes calls through us. If is_desk
- * but it isn't the desktop, we make is_desk false, and wait for trap_13
- * to change it (when the desktop returns, it resets the trap 2 vector
- * then does Setexec(101,...)).
- */
- if(is_desk) check_for_desk(TRUE);
- if(curapp->in_aes>1)
- DEBUG("lack: recursive call %d", cmd);
- switch(cmd)
- {
- case APPL_KILL:
- done=1; break; /* why is this here? */
- case APPL_INIT:
- curapp->action=APPL_INIT;
- break;
- case APPL_YIELD:
- if (aes_version < 0x200)
- {
- char *ssp=aes_appl->save_area->g_ssp;
-
- DEBUG("lack: faking appl_yield");
- if(apid <= 0x140)
- asm(" .short 0xf084":::
- "d0", "d1", "d2", "a0", "a1", "a2");
- else asm(" jsr _yield_aes":::
- "d0", "d1", "d2", "a0", "a1", "a2");
- aes_appl->save_area->g_ssp=ssp;
- leave_aes();
- done=1;
- }
- break;
- case APPL_EXIT:
- if(apid!=0)
- {
- DEBUG("catching appl_exit from apid %d", apid);
- done=1;
- }
- break;
- case MENU_REGISTER:
- if(get_menu_title) break;
- DEBUG("lack: faking menu register");
- strncpy(curapp->acc->menu_title, call->addr_in[0], 22);
- call->int_out[0]=curapp->acc->menu_index;
- done=1; break;
- case MENU_UNREGISTER:
- Menu_unregister();
- done=1; break;
- case MENU_BAR:
- if(apid!=0)
- {
- DEBUG("ignoring menu_bar from apid %d", apid);
- done=1;
- }else{
- DEBUG("menu_bar(%d, %lx)", call->int_in[0],
- call->addr_in[0]);
- print_global(call);
- curapp->action=RSRC_LOAD;
- }
- break;
- case RSRC_LOAD:
- DEBUG("rscr_load(%s)", call->addr_in[0]);
- case RSRC_FREE:
- print_global(call);
- curapp->action=RSRC_LOAD;
- break;
- case SHEL_FIND:
- DEBUG("shel_find(%s)", call->addr_in[0]);
- break;
- /* case FSEL_INPUT:
- case FSEL_XINPUT:*/
- /* I should always keep track of these things, so that I can fake topped and
- * untopped messages, and top all windows of a program running as an acc.
- * To work with programs I've got to do my own wind_new, this will
- * always cause problems with the desktop
- */
- case WIND_CREATE:
- curapp->action=WIND_CREATE;
- break;
- case WIND_DELETE:
- done=Wind_delete(call);
- break;
- case WIND_OPEN:
- done=Wind_open(call);
- break;
- case WIND_CLOSE:
- done=Wind_close(call);
- break;
- case WIND_UPDATE:
- done=Wind_update(call);
- break;
- case WIND_NEW:
- done=Wind_new(call);
- break;
- }
- in_aes=!done;
- if(done) curapp->in_aes-=1;
- return done;
- }
-
- int _super_aes(unsigned long coded_control)
- {
-
- curapp->in_aes+=1;
- /* call aes */
- __asm__ volatile
- (" movel %1, d1
- moval %0@, a0
- moveq #0, d0
- movepl d0, a0@(0) | clear high bytes of control array
- movepl d1, a0@(1)
- movl %0, d1
- movw #0xc8,d0 | note -- no movq here, it sign extends
- pea pc@(2f) |where trap #2 will return
- tstw 0x59e |longframe?
- beqs 1f
- clrw sp@-
- 1: movw sr, sp@-
- movl _gem+8, sp@-
- rts
- tas _use_trap_3
- trap #3
- 2: movl %0, __aesparams"
- : /* no outputs */
- : "a"(_aesparams), "g"(coded_control), "a"(__aes__) /* inputs */
- : "d0", "d1", "a0" /* clobbered regs */
- );
- __aes__=&_super_aes;
- leave_aes();
- return (int)_int_out[0];
- }
-
- Menu_unregister()
- {
- char *title=curapp->acc->menu_title;
-
- DEBUG("lack: faking menu unregister");
- strcpy(title, " "); title+=2;
- strcpy(title, curapp->acc->name); title+=8;
- strcpy(title, " <blank> ");
- }
-
-